package com.google.code.jholidays.events;

import com.google.code.jholidays.core.EventDescriptor;
import com.google.code.jholidays.events.parameters.DateParameters;
import com.google.code.jholidays.events.properties.FloatingEventProperties;
import com.google.code.jholidays.parsers.FloatingParser;

/**
 * Implements {@link AbstractFactory} for creating {@link FloatingEvent}
 * instances
 * 
 * @author tillias
 * 
 */
public class FloatingEventFactory extends AbstractFactory {

    /**
     * Creates new instance of factory
     */
    public FloatingEventFactory() {
	parser = new FloatingParser();
    }

    /**
     * {@inheritDoc}
     * <p>
     * This implementation attempts to create {@link DateParameters} object
     * using expression field of event descriptor. If succeeded method then
     * creates new instance of {@link FloatingEvent}
     */
    @Override
    protected AbstractEvent analizeExpression(EventDescriptor descriptor,
	    IEvent parent) {
	FloatingEvent result = null;

	try {
	    DateParameters parameters = getParameters(descriptor, parent);

	    result = createEvent(descriptor, parameters);
	} catch (Exception e) {
	    result = null;
	}

	return result;
    }

    /**
     * {@inheritDoc}
     * <p>
     * This implementation checks whether event descriptor passed to method
     * isn't null. If descriptor is not null and descriptor's expression field
     * is valid for building {@link DateParameters} instance returns true.
     * <p>
     * If descriptor parameter passed to this method is null or expression field
     * of descriptor can't be used to create {@link DateParameters} returns
     * false
     */
    @Override
    public boolean matches(EventDescriptor descriptor) {
	return parser.matches(descriptor.getExpression());
    }

    private FloatingEvent createEvent(EventDescriptor descriptor,
	    DateParameters params) {
	FloatingEvent result = null;

	try {
	    if (params != null) {
		FloatingEventProperties properties = new FloatingEventProperties(
			descriptor, params);

		result = new FloatingEvent(properties);

	    }
	} catch (Exception e) {
	    result = null;
	}

	return result;
    }

    private DateParameters getParameters(EventDescriptor descriptor,
	    IEvent parent) {
	DateParameters result = null;

	if (descriptor != null && verifyParent(descriptor, parent))
	    result = parser.parseParameters(descriptor.getExpression());

	return result;
    }

    private boolean verifyParent(EventDescriptor descriptor, IEvent parent) {
	boolean result = false;

	if (parent == null)
	    result = true;
	else {
	    if (parent.getID() == descriptor.getParentID())
		result = true;
	}

	return result;
    }

    FloatingParser parser;
}
